﻿/*  
	========================================================================
	 awzBoxes Library
	
	 Homepage: http://www.awzhome.de/
	========================================================================
	
	This Source Code Form is subject to the terms of the Mozilla Public
	License, v. 2.0. If a copy of the MPL was not distributed with this
	file, You can obtain one at http://mozilla.org/MPL/2.0/.
   
	The Original Code is code of awzBoxes Library.

	The Initial Developer of the Original Code is Andreas Weizel.
	Portions created by the Initial Developer are
	Copyright (C) 2011-2012 Andreas Weizel. All Rights Reserved.
	
	Contributor(s): (none)
	
	========================================================================
*/

using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Markup;
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;

namespace AWZhome.awzBoxes
{
	/// <summary>
	/// Representation of a horizontal line of boxes in a <see cref="AWZhome.awzBoxes.BoxArea"/> control.
	/// </summary>
	[ContentProperty("Boxes")]
	public partial class BoxLine : ContentControl
	{
		#region Dependency property definitions

		internal static readonly DependencyProperty LineIndexProperty =
					 DependencyProperty.Register("LineIndex", typeof(int), typeof(BoxLine), new UIPropertyMetadata(0));

		#endregion

		public BoxLine()
		{
			this.Boxes = new ObservableCollection<Box>();
			this.Boxes.CollectionChanged += Boxes_CollectionChanged;
			InitializeComponent();
		}

		public ObservableCollection<Box> Boxes
		{
			get;
			private set;
		}

		internal int LineIndex
		{
			get
			{
				return (int) GetValue(LineIndexProperty);
			}
			set
			{
				SetValue(LineIndexProperty, value);
			}
		}

		/// <summary>
		/// Sets the width of a specific column.
		/// </summary>
		/// <param name="index">Index of the grid column.</param>
		/// <param name="width">Column width to set.</param>
		public void SetColumnWidth(int index, double width)
		{
			this.SplittedGrid.SetColumnWidth(index, width);
		}

		/// <summary>
		/// Retrieves the width of a specific column.
		/// </summary>
		/// <param name="index">Index of the grid column.</param>
		/// <param name="actualWidth">If <c>true</c>, returns the actual width of the column.</param>
		/// <returns>The column width.</returns>
		public double GetColumnWidth(int index, bool actualWidth)
		{
			return this.SplittedGrid.GetColumnWidth(index, actualWidth) ?? 0f;
		}

		/// <summary>
		/// Retrieves the <see cref="AWZhome.awzBoxes.BoxArea"/> that contains the current box line.
		/// </summary>
		public BoxArea ParentBoxArea
		{
			get;
			internal set;
		}

		/// <summary>
		/// Determines whether the BoxLine belongs to a side bar.
		/// </summary>
		internal bool IsSideBar
		{
			get;
			set;
		}

		/// <summary>
		/// Gets/sets the internal ID of this BoxLine.
		/// </summary>
		internal int? ID
		{
			get;
			set;
		}

		public void Boxes_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{
			// Redirect all changes on Children collection to SplitterColumnGrid
			switch (e.Action)
			{
				case NotifyCollectionChangedAction.Add:
					foreach (FrameworkElement elem in e.NewItems)
					{
						this.SplittedGrid.Children.Insert(e.NewStartingIndex, elem);
						Box box = elem as Box;
						if (elem != null)
						{
							box.ParentBoxLine = this;
							box.IsSideBar = this.IsSideBar;
							if (!box.ID.HasValue)
							{
								if (this.Boxes.Count > 0)
								{
									box.ID = this.Boxes.Max(b => b.ID.HasValue ? b.ID.Value : -1) + 1;
								}
								else
								{
									box.ID = 0;
								}
							}
						}
					}
					break;

				case NotifyCollectionChangedAction.Move:
					break;

				case NotifyCollectionChangedAction.Remove:
					foreach (FrameworkElement elem in e.OldItems)
					{
						this.SplittedGrid.Children.Remove(elem);
						Box box = elem as Box;
						if (box != null)
						{
							box.ParentBoxLine = null;
							if ((this.Boxes.Count > 0) && (this.Boxes[0].Items.Count > 0))
							{
								this.Boxes[0].Items[0].IsActive = true;
							}
							box.ID = null;
						}
					}
					break;

				case NotifyCollectionChangedAction.Replace:
					foreach (FrameworkElement elem in e.OldItems)
					{
						this.SplittedGrid.Children.Remove(elem);
						Box box = elem as Box;
						if (box != null)
						{
							box.ParentBoxLine = null;
							if ((this.Boxes.Count > 0) && (this.Boxes[0].Items.Count > 0))
							{
								this.Boxes[0].Items[0].IsActive = true;
							}
							box.ID = null;
						}
					}
					foreach (FrameworkElement elem in e.NewItems)
					{
						this.SplittedGrid.Children.Add(elem);
						Box box = elem as Box;
						if (elem != null)
						{
							box.ParentBoxLine = this;
							box.IsSideBar = this.IsSideBar;
							if (!box.ID.HasValue)
							{
								if (this.Boxes.Count > 0)
								{
									box.ID = this.Boxes.Max(b => b.ID.HasValue ? b.ID.Value : -1) + 1;
								}
								else
								{
									box.ID = 0;
								}
							}
						}
					}
					break;

				case NotifyCollectionChangedAction.Reset:
					break;

				default:
					break;
			}

			// If there are no Boxes in here, remove this BoxLine from its container -> this should destroy it
			if (this.Boxes.Count == 0)
			{
				if (this.ParentBoxArea != null)
				{
					this.ParentBoxArea.BoxLines.Remove(this);
				}
			}
		}
	}
}
